package com.hz.house.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hz.house.bean.entity.ArticleCountBean;
import com.hz.house.bean.entity.ArticleDetailBean;
import com.hz.house.bean.entity.SellManDynamic;
import com.hz.house.common.ResultBean;
import com.hz.house.common.ResultUtil;
import com.hz.house.common.ThreadPool;
import com.hz.house.common.ZbDraw;
import com.hz.house.dao.ArticleMapper;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateFormatUtils;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;

/**
 * 买房必读文章相关
 */
@Service
@Slf4j
public class ArticleService {

    @Resource
    private ArticleMapper articleMapper;

    @Autowired
    private BbsCacheService bbsCacheService;

    @Autowired
    private ThreadPool threadPool;

    @Resource
    private RestTemplate ribbonTemplate;

    @Resource
    private RestTemplate restTemplate;

    private static final String ACCESS_KEY = "AKID7365oJHlilplYBmEfuyvfDfrUExTArfC";
    private static final String SECRET_KEY = "avqX0NULwJUmpTv61f5I5hc5RXMufJgp";

    /**
     * 获取token的服务地址 本系统
     */
    String GET_TOKEN_SERVICE = "http://house-small-building/ms/building/getXiaoChengxuTk";

    private Map<Integer, Integer> art_visit = new HashMap<>();

    private static final Map<Integer, String> cacheKey = new HashMap<>();

    public static String customerServiceUrl = "http://house-small-sellman/ms/customer";

    static {
        cacheKey.put(1, BbsCacheService.HOUSE_NEWS);
        cacheKey.put(2, BbsCacheService.ALONE_REPORT);
        cacheKey.put(3, BbsCacheService.MARKET_POLICY);
        cacheKey.put(4, BbsCacheService.LAND_MARKET);
    }

    /**
     * 查询文章列表
     *
     * @param type
     * @param page
     * @return
     */
    public ResultBean getArticleList(Integer type, Integer page) {
        if (!cacheKey.containsKey(type))
            return ResultUtil.fail("不存在的文章类型");
        if (page == null || page < 0)
            page = 1;
        String key = cacheKey.get(type);
        List<ArticleDetailBean> arts = bbsCacheService.getArticleList(key, page);
        if (arts == null) {
            // 存入本页数据
            int size = 10;
            arts = articleMapper.getArticleList((page - 1) * size, size, type);
            if (arts != null && arts.size() > 0) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                for (ArticleDetailBean art : arts) {
                    art.setShowTime(sdf.format(art.getCreateTime()));
                    art.setCreateTime(null);
                }
            }
            bbsCacheService.setArticlePageCache(page, key, arts);
        }
        Integer total = bbsCacheService.getArticleTotal(key);
        if (total == null) {
            total = articleMapper.getArticleTotal(type);
            bbsCacheService.setArticleTotal(key, total);
        }
        Map<String, Object> m = new HashMap<>();
        m.put("rows", arts);
        m.put("total", total);
        return ResultUtil.ok(m);
    }

    /**
     * 获取文章详情
     *
     * @param id
     * @return
     */
    public ResultBean getArticleDetail(Integer id) {
        ArticleDetailBean at = bbsCacheService.getArticleDetail(id);
        if (at == null) {
            at = articleMapper.getArticleDetail(id);
            if (at == null) {
                return ResultUtil.ok();
            }
            bbsCacheService.setArticleDetail(at);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        at.setShowTime(sdf.format(at.getCreateTime()));
        at.setCreateTime(null);
        if (at.getShowType() == 1) {// 外链
            at.setContent(null);
            at.setShowTime(null);
            at.setTitle(null);
        }
        at.setId(null);
        // 增加文章对应类型访问量
        addArticleVisit(at.getType());
        return ResultUtil.ok(at);
    }

    public ResultBean getArticleHb(Integer id, Integer customerId) {
        if (ObjectUtils.isEmpty(id)) {
            return ResultUtil.fail("生成海报失败");
        }
        //准备文章数据
        ArticleDetailBean articleDetail = articleMapper.getArticleDetail(id);
        if (articleDetail == null) {
            return ResultUtil.fail("生成海报失败");
        }
        //准备用户数据
        boolean isSellMan = this.isSellMan(customerId);
        //准备二维码
        byte[] qrCode;
        //本地二维码测试
        try {
            qrCode = this.getWenZhangQRCode(id, isSellMan ? customerId : null);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return ResultUtil.fail("生成海报失败");
        }

        if (qrCode == null || qrCode.length == 0) {
            log.error("获取小程序二维码失败");
            return ResultUtil.fail("生成海报失败");
        }
        //进行合成
        try {
            byte[] img = autoCreatePost(qrCode, articleDetail);
            if (img == null || img.length == 0) {
                return ResultUtil.fail("生成海报失败");
            }
            String imgStr = Base64.getEncoder().encodeToString(img);
            return ResultUtil.ok(null, imgStr);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return ResultUtil.fail("生成海报失败");
        }

    }

    private byte[] autoCreatePost(byte[] qrCode, ArticleDetailBean articleDetail) throws Exception {

        //750，1550
        int x = 750;
        int y = 1334;
        //创建底板画布
        BufferedImage billImgBuffer = new BufferedImage(x, y, BufferedImage.TYPE_INT_RGB);// RGB形式
        Graphics2D bill2d = billImgBuffer.createGraphics();
        bill2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//抗锯齿
        bill2d.setBackground(Color.WHITE);//设置背景为白色
        bill2d.clearRect(0, 0, 800, 1600);//通过使用当前绘图表面的背景色进行填充来清除指定的矩形
        //绘制背景图
        ZbDraw.drawBackGroundImg(bill2d, x, y, "https://housessmall-dev-index-img-1258778894.cos.ap-chengdu.myqcloud.com/icon/wz_bg.png");
        //绘制内容
        ZbDraw.drawZx(bill2d, articleDetail, 155);
        //绘制二维码
        ZbDraw.drawQrCode(bill2d, qrCode);
        //结束绘制,转成byte[]数组
        bill2d.dispose();
        FileOutputStream fos = new FileOutputStream(new File("D:\\text\\wzb.png"));
        ImageIO.write(billImgBuffer, "png", fos);
        fos.close();
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ImageIO.write(billImgBuffer, "png", byteOut);
        byte[] b = byteOut.toByteArray();
        return b;
    }

    /**
     * 获取微信小程序token
     *
     * @return
     */
    private String getXiaoChengxuToken() {
        String res = ribbonTemplate.getForObject(GET_TOKEN_SERVICE, String.class);
        JSONObject jo = JSON.parseObject(res);
        return jo.getString("data");
    }

    private byte[] getWenZhangQRCode(int zid, Integer sellManId) {
        String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit"
                + "?access_token=" + getXiaoChengxuToken();
        Map<String, String> m = new HashMap<>(16);
        m.put("page", "pages/media/graphic/details/main");
        String param = "id=" + zid + (sellManId == null ? "" : "&sid=" + sellManId);
        m.put("scene", param);
        HttpHeaders headers = new HttpHeaders();
        //设置请求媒体数据类型
        headers.setContentType(MediaType.APPLICATION_JSON);
        String json = JSON.toJSONString(m);
        HttpEntity<String> formEntity = new HttpEntity<>(json, headers);
        ResponseEntity<byte[]> res = restTemplate.postForEntity(url, formEntity, byte[].class);
        byte[] x = res.getBody();
        return x;
    }

    /**
     * 该用户是否可以在该楼盘下评论
     */
    public boolean isSellMan(int cid) {
        String url = customerServiceUrl + "/getSellManInfo?sellManCustomerId=" + cid;
        String res = ribbonTemplate.getForObject(url, String.class);
        log.info("服务内部调用置业顾问信息接口:" + res);
        JSONObject result = JSON.parseObject(res);
        int code = result.getIntValue("code");
        if (code != 200) {
            return false;
        }
        JSONObject data = result.getJSONObject("data");
        if (data == null) {
            return false;
        }
        Integer sellManBuildingId = data.getInteger("buildingId");
        return sellManBuildingId != null;
    }

    private void addArticleVisit(Integer type) {
        if (type == null)
            return;
        synchronized (art_visit) {
            Integer vs = art_visit.get(type);
            if (vs == null)
                art_visit.put(type, 1);
            else
                art_visit.put(type, vs + 1);
        }
    }

    /**
     * 获取社区置业顾问动态列表
     *
     * @param page
     * @return
     */
    public ResultBean getSellManDyns(Integer page) {
        if (page == null || page < 1)
            page = 1;
        List<SellManDynamic> dyns = bbsCacheService.getSellManDyns(page);
        if (dyns == null) {
            int size = 10;
            dyns = articleMapper.getSellManDyns((page - 1) * size, size);
            // 处理图片及展示时间
            dealImgAndTime(dyns);
            bbsCacheService.setSellManDyns(page, dyns);
        }
        Integer total = bbsCacheService.getDynamicTotal();
        if (total == null) {
            total = articleMapper.getDynamicTotal();
            bbsCacheService.setDynamicTotal(total);
        }
        Map<String, Object> m = new HashMap<>();
        m.put("total", total);
        m.put("rows", dyns);
        return ResultUtil.ok(m);
    }


    private void dealImgAndTime(List<SellManDynamic> dyns) {
        if (dyns != null && dyns.size() > 0) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            for (SellManDynamic dyn : dyns) {
                String imgStr = dyn.getImgStr();
                if (!StringUtils.isEmpty(imgStr)) {
                    dyn.setImgs(Arrays.asList(imgStr.split(",")));
                    dyn.setImgStr(null);
                }
                dyn.setShowTime(sdf.format(dyn.getCreateTime()));
                dyn.setCreateTime(null);
            }
        }
    }

    /**
     * 获取楼盘资讯列表
     *
     * @param page
     * @return
     */
    public ResultBean getManuscriptList(Integer page) {
        if (page == null || page < 1)
            page = 1;
        List<ArticleDetailBean> arts = bbsCacheService.getManuscriptList(page);
        if (arts == null) {
            int size = 10;
            arts = articleMapper.getManuscriptList((page - 1) * size, size);
            this.dealTime(arts);
            bbsCacheService.setManuscriptList(page, arts);
        }
        Integer total = bbsCacheService.getManuscriptTotal();
        if (total == null) {
            total = articleMapper.getManuscriptTotal();
            bbsCacheService.setManuscriptTotal(total);
        }
        Map<String, Object> m = new HashMap<>();
        m.put("total", total);
        m.put("rows", arts);
        return ResultUtil.ok(m);
    }

    /**
     * 将微信url转为html富文本
     *
     * @param url
     * @return
     */
    public ResultBean getHtmlByUrl(String url) throws IOException {
//        Document document = null;
//        try {
//            document = Jsoup.parse(new URL(url), 5000);
//        } catch (IOException e) {
//            e.fillInStackTrace();
//            log.info("解析url获取错误，url:{}", url);
//        }
        String _bucketName = "housing-price-evaluate-chat-1258778894";
//        Elements elements = document.getElementsByTag("img");
        COSClient cosClient = getCosClient();
//        elements.forEach(element -> {
//            if (element.hasAttr("data-src")) {
//                String imgUrl = element.attr("data-src");
//                if (StringUtils.isEmpty(imgUrl)){
//                    return;
//                }
//                String[] paramsSplit = "?".split(imgUrl);
//                String[] urlSplit = paramsSplit[paramsSplit.length].split("/");
//                String fileName = urlSplit[urlSplit.length];
//                Date date = new Date();
//                String key = "common/" + DateFormatUtils.format(date, "yyyyMMdd") + "/" + fileName;
//                byte[] bytes;
//                try {
//                    bytes = Jsoup.connect(imgUrl).ignoreContentType(true).execute().bodyAsBytes();
//                    InputStream in = new ByteArrayInputStream(bytes);
//                    PutObjectRequest putObjectRequest = new PutObjectRequest(_bucketName, key, in, new ObjectMetadata());
//                    cosClient.putObject(putObjectRequest);
//                    element.attr("src", "");
//                } catch (IOException e) {
//                    log.error("base64获取失败");
//                }
//            }
//        });
//        https://housing-price-evaluate-chat-1258778894.cos.ap-chengdu.myqcloud.com/h5/index.html
//        DaysIntUtil.FORMAT_yyMMddHHmmssSSS + (new Random()).nextInt(9))
        byte[] bytes = Jsoup.connect(url).ignoreContentType(true).execute().bodyAsBytes();
        InputStream in = new ByteArrayInputStream(bytes);
        Date date = new Date();
        String key = "h5/" + DateFormatUtils.format(date, "yyyyMMdd") + "/" + DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS") + ".html";
        PutObjectRequest putObjectRequest = new PutObjectRequest(_bucketName, key, in, new ObjectMetadata());
        cosClient.putObject(putObjectRequest);

        return ResultUtil.ok("https://" + _bucketName + ".cos.ap-chengdu.myqcloud.com/" + key);
    }

    public COSClient getCosClient() {
        // 1 初始化用户身份信息 secretId,SECRET_KEY
        COSCredentials cred = new BasicCOSCredentials(ACCESS_KEY, SECRET_KEY);
        // 2 设置bucket的区域
        ClientConfig clientConfig = new ClientConfig(new Region("ap-chengdu"));
        // 3 生成 cos 客户端。
        COSClient cosClient = new COSClient(cred, clientConfig);
        return cosClient;
    }

    private void dealTime(List<ArticleDetailBean> arts) {
        if (arts != null && arts.size() > 0) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            for (ArticleDetailBean art : arts) {
                art.setShowTime(sdf.format(art.getCreateTime()));
                art.setIsTop(null);
                art.setPublisherId(null);
                art.setCreateTime(null);
            }
        }
    }

    public void startCountWorker() {
        CountWorker cw = new CountWorker();
        Thread t = new Thread(cw);
        t.start();
    }

    class CountWorker implements Runnable {

        @Override
        public void run() {
            while (true) {
                try {
                    if (art_visit.size() > 0) {
                        synchronized (art_visit) {
                            dealVisit();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("买房必读访问量统计失败");
                } finally {
                    art_visit.clear();
                }
                try {
                    Thread.sleep(30000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        private void dealVisit() {
            try {
                List<ArticleCountBean> acs = new ArrayList<>();
                art_visit.forEach((k, v) -> {
                            ArticleCountBean ab = new ArticleCountBean();
                            ab.setType(k);
                            ab.setVisitNum(v);
                            acs.add(ab);
                        }
                );
                threadPool.runInThreadPool(() -> articleMapper.addVisits(acs));
            } catch (Exception e) {
                e.printStackTrace();
                log.error("买房必读统计异常");
            }
        }
    }
}
